using System;
using System.Linq;
using static QntPlatform.Strategy.CmdCtrl.StopLoss;
using static QntPlatform.Strategy.CmdCtrl.TrailingProfit;

namespace QntPlatform.Strategy.CmdCtrl
{
    /// <summary>
    /// 固定普通信号
    /// </summary>
    public class InTrade : CmdHandlePart
    {
        public InTrade(StrategyBase parent) : base(parent)
        {
        }
        decimal stopLossRatio=0.02m;
        public void Exec(TradeCmd cmdVal)
        {
            //解析
            var ret = Exchange.GetRecordsAsync(cmdVal.Period);
            var account = Exchange.GetAccountAsync();
            var tck = Exchange.GetTickerAsync();
            //仓位
            var stopLoss = CalcStopLoss(ret.Result, cmdVal.IsLong.Value);
            var amount = CalcAmount(cmdVal, stopLoss);
            var id = execTrade(DirectionTo.InFor(cmdVal.IsLong), amount);
            //止损
            var stopLossHandler = new StopLoss(this, new StopLossInfo() { Amount = amount, StopLossPrice = stopLoss, IsCloseBuy = cmdVal.IsLong.Value });
            //止盈
            var tpd = new TrailingProfitData();
            tpd.Amount = amount;
            tpd.InPrice = tck.Result.Buy;
            tpd.SourceOrderId = id;
            tpd.CloseDirection = DirectionTo.CloseFor(cmdVal.IsLong);
            var tp = new TrailingProfit(this, tpd);

            ev = (p1, p2) =>
            {
                if (stopLossHandler.Execute(p2))
                {
                    Exchange.TickerChangeEvent -= ev;
                    return;
                }
                if (tp.Execute(p2))
                {
                    Exchange.TickerChangeEvent -= ev;
                    return;
                }
            };
            Exchange.TickerChangeEvent += ev;

        }
        EventHandler<Ticker> ev;

        public decimal CalcAmount(TradeCmd cmdVal, decimal stopLoss)
        {
            //计算仓位
            var ret = Exchange.GetRecordsAsync(cmdVal.Period);
            var account = Exchange.GetAccountAsync();
            var tck = Exchange.GetTickerAsync();
            var kArr = ret.Result;
            //
            //var stopLoss=CalcStopLoss(kArr,cmdVal.IsLong.Value);
            //
            var nowPrice = tck.Result.Buy;
            var longVal = cmdVal.IsLong.Value ? 1 : -1;
            var buyAmount = longVal * account.Result.Balance * stopLossRatio / (nowPrice - stopLoss);
            log.Debug("交易信息计算", new { stopLoss, nowPrice, buyAmount, stopLossRatio });
            return buyAmount;

        }
        /// atr止损计算
        public decimal CalcStopLoss(Record[] records, bool isLong = true)
        {
            var last7 = records.Skip(records.Length - 7); // Aggregate((p1, p2) =>(p1 == null || p1.Low > p2.Low)?p2:p1);
            var top = isLong ? last7.Min(p => p.Low) : last7.Max(p => p.High);
            var atr = (decimal)TA.ATR(records, 14).Last();
            var atrV = isLong ? -atr * 0.5m : atr * 0.5m;
            var stopLoss = top + atrV; //止损价
            log.Debug("止损计算信息", new { top, atr, last7 });
            return stopLoss;
        }
        public class TradeCmd
        {
            public decimal? Price { get; set; }
            public decimal[] sells { get; set; }
            public int Period { get; set; }
            public bool? IsLong { get; set; }
        }
        public class OrderInfo
        {
            public IConvertible OrderId { get; set; }
            public SideDirection Direction { get; set; }
            public decimal Amount { get; set; }
            public decimal Price { get; set; }
            public DateTimeOffset? TradeTime { get; set; }
        }
    }
}
